'use client';

import type { TBody, TMetadata } from '@/types';
import { type ChangeEvent, useRef, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import type { IUploadAvatarFileBody } from '@/interfaces';
import { uploadAvatarFile } from '@/services/api';
import Script from 'next/script';
import useUser from '@/hooks/useUser';
import useToast, { LoginReminderContent } from '@/hooks/useToast';
import ErrorPage from '@/app/[locale]/error/error';
import LoadPage from '@/app/[locale]/load/load';
import { NavbarPage } from '@/app/[locale]/navbar';
import FooterPage from '@/app/[locale]/footer';
import { useTranslations } from 'use-intl';

export default function AvatarPage({ metadata }: { metadata: TMetadata }) {
  return (
    <>
      <NavbarPage metadata={metadata} />
      <Avatar metadata={metadata} />
      <FooterPage metadata={metadata} />
    </>
  );
}

const Avatar = ({ metadata }: { metadata: TMetadata }) => {
  const t = useTranslations('AvatarPage');
  const userQuery = useUser(metadata);
  const cropperImageRef = useRef(null);
  const cropperSelectionRef = useRef(null);
  const [isEdit, setIsEdit] = useState(
    !!(
      userQuery.data &&
      userQuery.data.user &&
      userQuery.data.user.details.largeAvatarUrl
    ),
  );
  const [form, setForm] = useState({
    avatar: '',
    file: '',
    fileObjectUrl: '',
  });

  const { show } = useToast();

  const uploadAvatarFileMutation = useMutation(
    async (variables: TBody<IUploadAvatarFileBody>) => {
      await uploadAvatarFile(variables);
    },
  );

  function clearUploadData() {
    if (form.fileObjectUrl) {
      URL.revokeObjectURL(form.fileObjectUrl);
    }
    setForm({
      avatar: '',
      file: '',
      fileObjectUrl: '',
    });
  }

  async function handleCallback(file: Blob) {
    if (!file) {
      show({
        type: 'DANGER',
        message: t('fileNotFound'),
      });
      return;
    }

    try {
      await uploadAvatarFileMutation.mutateAsync({
        data: {
          file,
        },
      });

      setIsEdit(true);
      clearUploadData();

      show({
        type: 'SUCCESS',
        message: isEdit ? t('updateAvatarComplete') : t('uploadAvatarComplete'),
      });

      setTimeout(() => {
        show({
          type: 'INFO',
          message: t('returnToHomePage'),
        });
      }, 1000);

      setTimeout(() => {
        location.href = `/users/${
          userQuery.data && userQuery.data.user && userQuery.data.user.id
        }`;
      }, 1500);
    } catch (e) {
      uploadAvatarFileMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickUpload() {
    if (isEdit) {
      if (!confirm(t('confirmUpdateExistingAvatar'))) {
        return;
      }
    }

    if (!(userQuery.data && userQuery.data.user)) {
      show({
        title: t('loginPrompt'),
        content: <LoginReminderContent />,
      });
      return;
    }

    const current = cropperSelectionRef.current;
    if (!current || !cropperImageRef.current) {
      show({
        type: 'DANGER',
        message: t('cropElementNotFound'),
      });
      return;
    }

    const { file } = form;
    if (!file) {
      show({
        type: 'DANGER',
        message: t('fileNotUploaded'),
      });
      return;
    }

    try {
      // @ts-ignore
      const canvas = await current.$toCanvas({
        // @ts-ignore
        beforeDraw: (context, canvas) => {
          const { width, height } = canvas;

          if (width !== 260 || height !== 260) {
            const message = t('invalidCropDimensions');
            show({
              type: 'DANGER',
              message,
            });
            return Promise.reject(message);
          }
          return Promise.resolve();
        },
      });

      // @ts-ignore
      canvas.toBlob(handleCallback, file.type, 1);
    } catch (e: any) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickTop() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(0, -6);
    }
  }

  function onClickBottom() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(0, 6);
    }
  }

  function onClickLeft() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(-6, 0);
    }
  }

  function onClickRight() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$translate(6, 0);
    }
  }

  function onClickPlus() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$zoom(0.1);
    }
  }

  function onClickDash() {
    if (cropperImageRef.current) {
      // @ts-ignore
      cropperImageRef.current.$zoom(-0.1);
    }
  }

  function onClickReset() {
    if (cropperImageRef.current && cropperSelectionRef.current) {
      // @ts-ignore
      cropperImageRef.current.$resetTransform();
      // @ts-ignore
      cropperImageRef.current.$center('cover');
      // @ts-ignore
      cropperSelectionRef.current.$change(0, 0, 260, 260);
      // @ts-ignore
      cropperSelectionRef.current.$center();
    }
  }

  function onChangeForm(
    e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'avatar') {
      if (form.fileObjectUrl) {
        URL.revokeObjectURL(form.fileObjectUrl);
      }

      const file = (e.target as any).files[0];
      const fileObjectUrl = URL.createObjectURL(file);
      setForm({
        ...form,
        [name]: value,
        file,
        fileObjectUrl,
      });
    }
  }

  function onLoadCropper() {
    if (cropperImageRef.current && cropperSelectionRef.current) {
      // @ts-ignore
      cropperImageRef.current.$ready(() => {
        // @ts-ignore
        cropperSelectionRef.current.$center();
      });
    }
  }

  if (userQuery.data) {
    return (
      <>
        <div className="col px-0">
          <div className="card border-0">
            <div className="card-body py-4">
              <div className="lead text-center mt-4">
                {isEdit ? t('editAvatar') : t('uploadNewAvatar')}
              </div>
              <div className="row my-5 mx-0">
                <div className="col d-flex align-items-center justify-content-center flex-column">
                  {/*// @ts-ignore*/}
                  <cropper-canvas
                    style={{ width: 330, height: 330 }}
                    id="cropper-canvas"
                    background
                  >
                    {/*// @ts-ignore*/}
                    <cropper-image
                      ref={cropperImageRef}
                      rotatable="false"
                      skewable="false"
                      id="cropper-image"
                      src={form.fileObjectUrl || '/images/avatar.png'}
                      alt="avatar"
                    >
                      {/*// @ts-ignore*/}
                    </cropper-image>
                    {/*// @ts-ignore*/}
                    <cropper-shade></cropper-shade>
                    {/*// @ts-ignore*/}
                    <cropper-handle action="select" plain></cropper-handle>
                    {/*// @ts-ignore*/}
                    <cropper-selection
                      ref={cropperSelectionRef}
                      width="260"
                      height="260"
                      id="cropper-selection"
                      movable
                      resizable
                      outlined
                    >
                      {/*// @ts-ignore*/}
                      <cropper-grid role="grid" hidden></cropper-grid>
                      {/*// @ts-ignore*/}
                      <cropper-crosshair centered></cropper-crosshair>
                      {/*// @ts-ignore*/}
                      <cropper-handle
                        className="rounded-circle"
                        action="move"
                        theme-color="rgba(255, 255, 255, 0.35)"
                      >
                        {/*// @ts-ignore*/}
                      </cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="n-resize" hidden></cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="e-resize" hidden></cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="s-resize" hidden></cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="w-resize" hidden></cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="ne-resize" hidden>
                        {/*// @ts-ignore*/}
                      </cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="nw-resize" hidden>
                        {/*// @ts-ignore*/}
                      </cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="se-resize" hidden>
                        {/*// @ts-ignore*/}
                      </cropper-handle>
                      {/*// @ts-ignore*/}
                      <cropper-handle action="sw-resize" hidden>
                        {/*// @ts-ignore*/}
                      </cropper-handle>
                      {/*// @ts-ignore*/}
                    </cropper-selection>
                    {/*// @ts-ignore*/}
                  </cropper-canvas>
                  <div className="hstack gap-2 flex-wrap justify-content-center my-5">
                    <button
                      onClick={onClickTop}
                      type="button"
                      className="btn btn-light"
                    >
                      {t('moveUp')}
                    </button>
                    <button
                      onClick={onClickBottom}
                      type="button"
                      className="btn btn-light"
                    >
                      {t('moveDown')}
                    </button>
                    <button
                      onClick={onClickLeft}
                      type="button"
                      className="btn btn-light"
                    >
                      {t('moveLeft')}
                    </button>
                    <button
                      onClick={onClickRight}
                      type="button"
                      className="btn btn-light"
                    >
                      {t('moveRight')}
                    </button>
                    <button
                      onClick={onClickPlus}
                      type="button"
                      className="btn btn-light"
                    >
                      {t('zoomIn')}
                    </button>
                    <button
                      onClick={onClickDash}
                      type="button"
                      className="btn btn-light"
                    >
                      {t('zoomOut')}
                    </button>
                    <button
                      onClick={onClickReset}
                      type="button"
                      className="btn btn-light"
                    >
                      {t('update')}
                    </button>
                  </div>
                </div>
                <div className="col d-flex align-items-center justify-content-center flex-column">
                  <div className="row">
                    <div className="col">
                      <div className="input-group">
                        <input
                          disabled={uploadAvatarFileMutation.isLoading}
                          type="file"
                          accept="image/*"
                          className="form-control"
                          id="avatar"
                          name="avatar"
                          value={form.avatar}
                          onChange={onChangeForm}
                          aria-describedby="inputGroupFileAddon04"
                          aria-label="Upload"
                        />
                        <button
                          onClick={onClickUpload}
                          disabled={uploadAvatarFileMutation.isLoading}
                          className="btn btn-outline-secondary"
                          type="button"
                          id="inputGroupFileAddon04"
                        >
                          {uploadAvatarFileMutation.isLoading && (
                            <span
                              className="spinner-border spinner-border-sm me-2"
                              role="status"
                              aria-hidden="true"
                            ></span>
                          )}
                          {isEdit ? t('update') : t('uploadNewAvatar')}
                        </button>
                      </div>
                      <ol className="form-text">
                        <li>{t('selectAvatarToCrop')}</li>
                        <li>{t('zoomWithMouseOrButton')}</li>
                      </ol>
                    </div>
                  </div>
                  <div className="row my-5">
                    <div className="col d-flex justify-content-center align-items-center">
                      {/*// @ts-ignore*/}
                      <cropper-viewer
                        className="rounded-circle"
                        selection="#cropper-selection"
                        style={{ width: 260 }}
                      >
                        {/*// @ts-ignore*/}
                      </cropper-viewer>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <Script src="/lib/cropper.min.js" onLoad={onLoadCropper} />
      </>
    );
  }

  if (userQuery.error) {
    return <ErrorPage error={userQuery.error} />;
  }

  return <LoadPage />;
};
